package com.yuandian.customer.perception.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.yuandian.api.customer_perception.constant.StatTypeEnum;
import com.yuandian.api.customer_perception.po.KhgzSystemParams;
import com.yuandian.api.customer_perception.po.LowFrequenceSystemParams;
import com.yuandian.api.customer_perception.vo.*;
import com.yuandian.api.management.entity.ConfSystem;
import com.yuandian.api.management.feign.RemoteSystemService;
import com.yuandian.bpm.admin.api.entity.SysDictItem;
import com.yuandian.bpm.admin.api.feign.RemoteDictService;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.constant.DictType;
import com.yuandian.customer.perception.mapper.LowFrequencySysOverviewMapper;
import com.yuandian.customer.perception.service.ILowFrequencySysOverviewService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 说明：低频受理业务概况service实现
 * @Author yanjun
 * @Date 2021年4月14日 上午9:19:49
 */
@Service
@Slf4j
public class LowFrequencySysOverviewServiceImpl implements ILowFrequencySysOverviewService {

	@Autowired
	private LowFrequencySysOverviewMapper lowFrequencySysOverviewMapper;
	@Autowired
	private RemoteSystemService systemDomainService;

	@Autowired
	private RemoteDictService remoteDictService;


	private static final Map<Integer, List<SystemDomainInfo>> data = new HashMap<>();

	/**
	 * 查询低频受理系统概况列表
	 * @param params
	 * @return
	 */
    //@DS("khgzData")
	@Override
	public LowFrequencySystemOverviewVo querySystemOverviewList(LowFrequenceSystemParams params) {
		// 设置表名
		params.setTableName(StatTypeEnum.valueOf(params.getType()).getTableName());
		// 设置时间周期
		LocalDateTime dateTime = null;
		if (params.getType() == 1) {
			dateTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN).with(DayOfWeek.MONDAY);
		} else {
			dateTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN).with(TemporalAdjusters.firstDayOfMonth());
		}
		long milli = dateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli() * 1000;
		// 如果有传进来cycleTimeUsec,则采用它
		if (params.getCycleTimeUsec() != null) {
			milli = params.getCycleTimeUsec() * 1000;
		}
		params.setCycleTimeUsec(milli);

		// 查询数据
		List<Map<String, Object>> list = lowFrequencySysOverviewMapper.querySystemOverviewList(params);
		List<SystemOverview> data = new ArrayList<>();
        LowFrequencySystemOverviewVo result = new LowFrequencySystemOverviewVo();
		Map<String, SystemDomainInfo> systemDomainInfoMap = getSystemDomainInfo();
		Iterator<Map.Entry<String, SystemDomainInfo>> iterator = systemDomainInfoMap.entrySet().iterator();

		if (list == null || list.isEmpty() || list.size() < 1) {
            // 当不存在数据，组装空数据
            while (iterator.hasNext()) {
                Map.Entry<String, SystemDomainInfo> next = iterator.next();
                SystemDomainInfo systemDomainInfo = next.getValue();
                SystemOverview systemOverviewVo = new SystemOverview();
                systemOverviewVo.setSystemDomainId(systemDomainInfo.getSystemDomainId());
                systemOverviewVo.setSystemDomainName(systemDomainInfo.getSystemDomainName());
                systemOverviewVo.setData(new ArrayList<>());
                data.add(systemOverviewVo);
            }
            result.setSystemOverviewVoList(data);
            return result;
		}
        SystemPieDataVo systemPieDataVo = new SystemPieDataVo();
		List<SystemPieDataVo> dataList = new ArrayList<>();
		for (int i = 0; i < list.size(); i++) {
			Map<String, Object> oneMap = list.get(i);
			String oneSystemId = oneMap.get("systemId").toString();
			systemPieDataVo = new SystemPieDataVo();
			systemPieDataVo.setSystemId(Integer.valueOf(oneSystemId));
			systemPieDataVo.setSystemName(oneMap.getOrDefault("systemName","未知").toString());
			String oneValueStr = oneMap.get("value").toString();
			int oneValue = Integer.valueOf(oneValueStr);
			String oneStateStr = oneMap.get("state").toString();
			if (oneStateStr.equals("1")) {
				systemPieDataVo.setNormalValue(oneValue);
			} else {
				systemPieDataVo.setAbnormalValue(oneValue);
			}
			systemPieDataVo.setTotal(oneValue);
			for (int j = list.size() - 1; j > i; j--) {
				Map<String, Object> twoMap = list.get(j);
				String twoSystemId = twoMap.get("systemId").toString();
				String twoStateStr = twoMap.get("state").toString();
				if (oneSystemId.equals(twoSystemId)) {
					String twoValueStr = twoMap.get("value").toString();
					int twoValue = Integer.valueOf(twoValueStr);
					if (twoStateStr.equals("1")) {
						systemPieDataVo.setNormalValue(twoValue);
					} else {
						systemPieDataVo.setAbnormalValue(twoValue);
					}
					systemPieDataVo.setTotal(oneValue + twoValue);
					list.remove(j);
				}
			}
			dataList.add(systemPieDataVo);
		}

        // 根据低频和空置比例排序
        Collections.sort(dataList, (SystemPieDataVo data1, SystemPieDataVo data2) -> {
            double rate1 = (double) data1.getAbnormalValue() / data1.getTotal();
            double rate2 = (double) data2.getAbnormalValue() / data2.getTotal();
            if (rate1 < rate2 || (rate1 == rate2 && data1.getAbnormalValue() < data2.getAbnormalValue())) {
                return 1;
            }
            if (rate1 < rate2
                    || (rate1 == rate2 && data1.getAbnormalValue() < data2.getAbnormalValue())
                    || (rate1 == rate2 && data1.getAbnormalValue() == data2.getAbnormalValue() && data1.getNormalValue() < data2.getNormalValue())) {
                return 1;
            }
            return -1;
        });

        List<SystemPieDataVo> systemPieAllData = new ArrayList<>();

        // 封装数据
		while (iterator.hasNext()) {
			Map.Entry<String, SystemDomainInfo> next = iterator.next();
			SystemDomainInfo systemDomainInfo = next.getValue();
			// 这个域下面所有系统
			Set<Integer> systemIdSet = systemDomainInfo.getSystemIdList();
            // 获取该域下面所有系统对象
            List<ConfSystem> systemAndDomainInfoList = systemDomainInfo.getSystemAndDomainInfoList();
            List<Integer> systemIdList = new ArrayList<>();

			SystemOverview systemOverviewVo = new SystemOverview();
			systemOverviewVo.setSystemDomainId(systemDomainInfo.getSystemDomainId());
			systemOverviewVo.setSystemDomainName(systemDomainInfo.getSystemDomainName());

            List<SystemPieDataVo> systemPieDataVoList = new ArrayList<>();
            for (int i = 0; i < dataList.size(); i++) {
                SystemPieDataVo systemPieData = dataList.get(i);
                Integer systemId = systemPieData.getSystemId();
                if (systemIdSet.contains(systemId)) {
                    systemPieDataVoList.add(systemPieData);
                    // 临时记录哪些系统加入到了 systemPieDataVoList 里面
                    systemIdList.add(systemId);
                }
            }

            /*
			 如果前端查询条件为‘所有域’和‘所有系统’时:
							检查 systemPieDataVoList (systemIdList) 中是否加入了 systemIdSet 里面的所有系统,
						    如果不包含则需要补上相应系统（针对BUG：5268）
			 */
            if (params.getSystemId() == null || params.getSystemId().length == 0) {
                for (int j = 0; j < systemAndDomainInfoList.size(); j++) {
                    ConfSystem systemAndDomainInfo = systemAndDomainInfoList.get(j);
                    if (!systemIdList.contains(systemAndDomainInfo.getId())) {
                        SystemPieDataVo systemPieData = new SystemPieDataVo();
                        systemPieData.setSystemId(systemAndDomainInfo.getId());
                        systemPieData.setSystemName(systemAndDomainInfo.getName());
                        systemPieData.setTotal(0);
                        systemPieData.setAbnormalValue(0);
                        systemPieData.setNormalValue(0);
                        systemPieDataVoList.add(systemPieData);
                    }
                }
            }

            systemOverviewVo.setData(systemPieDataVoList);
            systemPieAllData.addAll(systemPieDataVoList);
            data.add(systemOverviewVo);

            // 如果携带了系统参数，每次循环一轮后判断数据是否存在，如果存在则直接跳出循环，减少不必要的循环
            if (params.getSystemId() != null && params.getSystemId().length > 0 && !systemPieDataVoList.isEmpty() && systemPieDataVoList.size() > 0) {
                break;
            }
		}
        // 封装按域分区的结果集
        result.setSystemOverviewVoList(data);

        // 根据低频和空置比例排序 无划分域 的List
        Collections.sort(systemPieAllData, (SystemPieDataVo data1, SystemPieDataVo data2) -> {
            double rate1 = data1.getTotal() == 0 ? 0 : (double) data1.getAbnormalValue() / data1.getTotal();
            double rate2 = data2.getTotal() == 0 ? 0 : (double) data2.getAbnormalValue() / data2.getTotal();
            if (rate1 < rate2
                    || (rate1 == rate2 && data1.getAbnormalValue() < data2.getAbnormalValue())
                    || (rate1 == rate2 && data1.getAbnormalValue() == data2.getAbnormalValue() && data1.getNormalValue() < data2.getNormalValue())) {
                return 1;
            }
            return -1;
        });
        result.setSystemPieDataVoList(systemPieAllData);

        return result;
	}

	public Map<String, SystemDomainInfo> getSystemDomainInfo() {
		// 系统与域信息
		ConfSystem confSystem = new ConfSystem();
		R<List<ConfSystem>> r = systemDomainService.list(confSystem);
		if(r.getCode() != 200){
			log.error("[客户感知-调用配置模块]-查询系统列表失败：{}", r.getMsg());
		}

		// 获取系统域名
		Map<String, String> systemDomainMap = remoteDictService.getDictByType(DictType.SYSTEM_DOMAIN).getData().stream().collect(Collectors.toMap(SysDictItem::getItemValue, SysDictItem::getLabel));
		if (CollectionUtil.isEmpty(systemDomainMap)) { systemDomainMap = new HashMap<>(); }

		List<ConfSystem> systemAndDomainInfoList = r.getData();
		Map<String, SystemDomainInfo> systemDomainInfoMap = new HashMap<>();
		for (ConfSystem systemAndDomainInfo : systemAndDomainInfoList){
			String systemDomainId = systemAndDomainInfo.getDomainCode();
			String systemDomainName = systemDomainMap.get(systemDomainId);
			SystemDomainInfo systemDomainInfo = systemDomainInfoMap.get(systemDomainId);
			if (systemDomainInfo == null) {
				systemDomainInfo = new SystemDomainInfo();
				systemDomainInfo.setSystemDomainId(systemDomainId);
				systemDomainInfo.setSystemDomainName(systemDomainName);
			}
			Set<Integer> systemIdList = systemDomainInfo.getSystemIdList();
			if (systemIdList == null || systemIdList.isEmpty()) {
				systemIdList = new HashSet<>();
			}
			systemIdList.add(systemAndDomainInfo.getId());
			systemDomainInfo.setSystemIdList(systemIdList);
			List<ConfSystem> systemAndDomainInfos = systemDomainInfo.getSystemAndDomainInfoList();
			if (systemAndDomainInfos == null || systemAndDomainInfos.isEmpty()) {
				systemAndDomainInfos = new ArrayList<>();
			}
			systemAndDomainInfos.add(systemAndDomainInfo);
			systemDomainInfo.setSystemAndDomainInfoList(systemAndDomainInfos);
			systemDomainInfoMap.put(systemDomainId, systemDomainInfo);
		}
		return systemDomainInfoMap;
	}


	/**
	 * 查询低频受理 系统域 与 系统 下拉框数据源
	 */
	@Override
	public List<SystemOverview> querySystemOverviewOptions() {
		// 查询数据
		List<SystemOverview> data = new ArrayList<>();
		// 系统与域信息
		Map<String, SystemDomainInfo> systemDomainInfoMap = getSystemDomainInfo();
		Iterator<Map.Entry<String, SystemDomainInfo>> iterator = systemDomainInfoMap.entrySet().iterator();
		while (iterator.hasNext()) {
			Map.Entry<String, SystemDomainInfo> next = iterator.next();
			SystemDomainInfo systemDomainInfo = next.getValue();
			SystemOverview systemOverviewVo = new SystemOverview();
			systemOverviewVo.setSystemDomainId(systemDomainInfo.getSystemDomainId());
			systemOverviewVo.setSystemDomainName(systemDomainInfo.getSystemDomainName());
			systemOverviewVo.setSystemAndDomainInfoList(systemDomainInfo.getSystemAndDomainInfoList());
			data.add(systemOverviewVo);
		}
		return data;
	}

	/**
	 * 查询系统列表
	 */
 	@Override
	public List<KhgzSystemInfoVo> getSystemListByDomain(KhgzSystemParams params) {
		List<KhgzSystemInfoVo> systemInfoVoList = new ArrayList<>();
		Map<String, SystemDomainInfo> systemDomainInfoMap = getSystemDomainInfo();
		SystemDomainInfo systemDomainInfo = systemDomainInfoMap.get(params.getSystemDomainId());
		List<ConfSystem> systemAndDomainInfoList = systemDomainInfo == null ? new ArrayList<>() : systemDomainInfo.getSystemAndDomainInfoList();
		for (ConfSystem systemAndDomainInfo : systemAndDomainInfoList) {
			if (!StringUtils.isNotEmpty(params.getSystemName())) {
				initSystemInfo(systemInfoVoList, systemAndDomainInfo);
				continue;
			}
			if (systemAndDomainInfo.getName().contains(params.getSystemName())) {
				initSystemInfo(systemInfoVoList, systemAndDomainInfo);
			}
		}
		return systemInfoVoList;
	}


	/**
	 * 初始化KhgzSystemInfoVo
	 */
	private void initSystemInfo(List<KhgzSystemInfoVo> systemInfoList, ConfSystem systemDomainInfo) {
		KhgzSystemInfoVo systemInfoVo = new KhgzSystemInfoVo();
		systemInfoVo.setSystemDomainId(systemDomainInfo.getDomainCode());
		systemInfoVo.setSystemDomainName(systemDomainInfo.getDomainName());
		systemInfoVo.setSystemId(systemDomainInfo.getId());
		systemInfoVo.setSystemName(systemDomainInfo.getName());
		systemInfoList.add(systemInfoVo);
	}

}
